package com.xb.loan.cashier.biz.task.alipay;

import com.xb.loan.cashier.biz.dao.bean.CashierPayChannel;
import com.xb.loan.cashier.biz.dao.bean.CashierPlatPaytype;
import com.xb.loan.cashier.biz.pay.alipay.AlipayErrorCode;
import com.xb.loan.cashier.biz.pay.alipay.AlipayPayment;
import com.xb.loan.cashier.biz.pay.alipay.config.AlipayConfig;
import com.xb.loan.cashier.biz.pay.alipay.util.AlipayNotify;
import com.xb.loan.cashier.biz.service.CashierChargeOrderService;
import com.xb.loan.cashier.biz.service.CashierPayChannelService;
import com.xb.loan.cashier.biz.service.CashierPlatPaytypeService;
import com.xb.loan.cashier.biz.task.ThirdQueryChargeTask;
import com.xb.loan.cashier.biz.task.plat.PushChargeTask;
import com.xb.loan.cashier.biz.util.XMLUtil;
import com.xb.loan.cashier.service.constant.ICashierEnumConst;
import com.xb.loan.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 第三方单笔查询任务
 */
@Component(value="alipayWapQueryChargeTask")
@Scope(value="prototype")
public class AlipayWapQueryChargeTask extends ThirdQueryChargeTask {
    
    private static final Logger log = LoggerFactory.getLogger(AlipayWapQueryChargeTask.class);

    @Autowired
    private CashierChargeOrderService cashierChargeOrderService;
    @Autowired
    private CashierPayChannelService cashierPayChannelService;
    @Autowired
    private CashierPlatPaytypeService cashierPlatPaytypeService;
    
    /**
     *1.获取支付宝支付配置相关信息
     *2.校验支付宝返回数据是否被篡改
     *3.根据返回结果修改订单状态(存在并发情况),如果更新失败先查询订单状态是否为成功
     *
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Override
	public void execute() {
	    log.info("execute 开始处理订单 orderId="+cashierChargeOrder.getOrderId()+",platId="+cashierChargeOrder.getPlatId()+",partnerId="+cashierChargeOrder.getPartnerId()+",payChannelType="+cashierChargeOrder.getPayChannelType());
	    int status = 0;
	    String tradeStatus = null;
	    String tradeNo = null;
	    String outTradeNo = null;
	    String gmtCreate = null;
	    double totalFee = 0;
        String errorCode = null;
        String errorMsg = null;
        CashierPayChannel cpc = cashierPayChannelService.queryByChannelId(cashierChargeOrder.getPayChannelId());
        if (cpc==null) {
            log.info("execute 支付渠道信息不存在 platId="+cashierChargeOrder.getPlatId()+",payChannelType="+cashierChargeOrder.getPayChannelType());
            return;
        }
        CashierPlatPaytype cpp = cashierPlatPaytypeService.queryEntity(cashierChargeOrder.getPlatId(), cpc.getPayChannelId());
        if (cpp==null) {
            log.info("execute 平台信息不存在 platId="+cashierChargeOrder.getPlatId()+",payChannelId="+cpc.getPayChannelId());
            return;
        }
        Map<String, Object> map = null;
        String partner = cpc.getChannelUser();//合作者身份ID
        String orderId = cashierChargeOrder.getOrderId();
        String signType = cpp.getEncryptType()== ICashierEnumConst.CashierEncryptType.MD5.getEncryptType()? ICashierEnumConst.CashierEncryptType.MD5.getDesc(): ICashierEnumConst.CashierEncryptType.RSA.getDesc();
        String signKey = cpp.getEncryptType()== ICashierEnumConst.CashierEncryptType.MD5.getEncryptType()?cpc.getMd5Key():cpc.getPrivateKey();
        String queryUrl = cpc.getQueryUrl();
        try {
            String result = AlipayPayment.singleTradeQuery(partner, orderId, signType, signKey, queryUrl);
            if (StringUtils.isEmpty(result)) {
                log.info("execute result is null!");
            }
            map = XMLUtil.parse(result.getBytes(AlipayConfig.input_charset));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        
        String isSucc = (String)map.get("is_success");
        
        if ("T".equals(isSucc)) {
            //返回状态
            tradeStatus = ((Map)((Map)map.get("response")).get("trade")).get("trade_status").toString();
            //支付宝交易流水
            tradeNo = ((Map)((Map)map.get("response")).get("trade")).get("trade_no").toString();
            //商户订单号
            outTradeNo = ((Map)((Map)map.get("response")).get("trade")).get("out_trade_no").toString();
            //交易创建时间
            gmtCreate = ((Map)((Map)map.get("response")).get("trade")).get("gmt_create").toString();
            //交易金额
            totalFee = Double.parseDouble(((Map)((Map)map.get("response")).get("trade")).get("total_fee").toString());
            
            log.info("execute 支付宝返回参数: is_success="+isSucc+",trade_status="+tradeStatus+",trade_no="+tradeNo+",out_trade_no="+outTradeNo+",gmt_create="+gmtCreate+",totalFee="+totalFee);
            //验签
            Map<String, String> signMap = (Map)((Map)map.get("response")).get("trade");
            log.info("execute 验签数据："+signMap);
            String sign = map.get("sign").toString();
            signKey = cpp.getEncryptType()== ICashierEnumConst.CashierEncryptType.MD5.getEncryptType()?cpc.getMd5Key():cpc.getThirdPubkey();
            boolean b = AlipayNotify.verify(signMap,sign,signType,signKey);
            if(b) {
                String tradeMsg = AlipayErrorCode.getErrorMsg(AlipayPayment.MODULE_SINGLE_TRADE_QUERY, tradeStatus);
                log.info("execute orderId="+cashierChargeOrder.getOrderId()+",tradeStatus="+tradeStatus+",tradeMsg="+tradeMsg);
                if(AlipayPayment.TRADE_FINISHED.equals(tradeStatus) || AlipayPayment.TRADE_SUCCESS.equals(tradeStatus)){
                    status = ICashierEnumConst.CashierChargeStatus.SUCCESS.getStatus();
                }else if(AlipayPayment.TRADE_CLOSED.equals(tradeStatus)) {
                    status = ICashierEnumConst.CashierChargeStatus.FAIL.getStatus();
                    errorCode = tradeStatus;
                    errorMsg = tradeMsg;
                }else {
                    return;//中间状态记录日志直接退出
                }
                
            } else {
                log.info("execute 验签不通过 orderId="+cashierChargeOrder.getOrderId());
                return;
            }
        }else {
            //查询出错
            String errorStatus = map.get("error").toString();
            errorCode = errorStatus;
            errorMsg = AlipayErrorCode.getErrorMsg(AlipayPayment.MODULE_SINGLE_TRADE_QUERY, errorCode);
            log.info("execute orderId="+cashierChargeOrder.getOrderId()+",errorCode="+errorCode+",errorMsg="+errorMsg);
            //订单在支付宝端不存在
            if(AlipayPayment.TRADE_NOT_EXIST.equals(errorStatus)) {
                if (isTimeOut()) {//超时
                    status = ICashierEnumConst.CashierChargeStatus.FAIL.getStatus();
                    log.info("execute orderId="+cashierChargeOrder.getOrderId()+" 第三方订单不存在且创建已超时,该订单将会被处理为失败!");
                }else {
                    return;
                }
            } else {
                return;//其它状态记录日志直接退出,下次重试
            }
        }
        int res = cashierChargeOrderService.updateByOrderId(null,null,cashierChargeOrder.getOrderId(),gmtCreate,status,tradeNo,errorCode,errorMsg);
        if (res>0) {
            PushChargeTask pct = (PushChargeTask)ctx.getBean("pushChargeTask");
            cashierChargeOrder.setStatus(status);
            pct.setCashierChargeOrder(cashierChargeOrder);
            pct.execute();
            log.info("execute 更新状态成功 orderId="+cashierChargeOrder.getOrderId()+",platId="+cashierChargeOrder.getPlatId()+",partnerId="+cashierChargeOrder.getPartnerId());
        } else {
            int state = cashierChargeOrderService.queryStatus(cashierChargeOrder.getOrderId(), null, null);
            if (state==ICashierEnumConst.CashierChargeStatus.WAIT.getStatus()) {
                log.info("execute 更新状态失败 orderId="+cashierChargeOrder.getOrderId()+",platId="+cashierChargeOrder.getPlatId()+",partnerId="+cashierChargeOrder.getPartnerId());
            }
        }
	}
    
}
